package study.test.ld.serurity;

import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import com.sun.crypto.provider.SunJCE;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 加密解密相关
 * 
 * @ClassName SecurityService
 * @author <a href="mailto:donggongai@126.com" target="_blank">kevin</a>
 * @date 2016年8月25日 下午2:54:43
 *
 */
@Slf4j
public class SecurityService {
    private final static Map<String, Cipher> cipherMap = new HashMap<String, Cipher>();
    private final static char[] DIGEST_ARRAY = "0123456789abcdef".toCharArray();

    /**
     * 
     * SHA1加密
     * 
     * @Title SHA1
     * @param data
     *            要加密字符
     * @return
     * @throws NoSuchAlgorithmException
     *             String
     */
    public final static String SHA1(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] b = md.digest(data.getBytes());
        return byte2hex(b);
    }

    /**
     * 
     * MD5加密
     * 
     * @Title MD5
     * @param data
     *            要加密字符
     * @return
     * @throws NoSuchAlgorithmException
     *             String
     */
    public final static String MD5(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] b = md.digest(data.getBytes());
        return byte2hex(b);
    }

    private final static Cipher getEncryptCipher(String strKey) throws Exception {
        String key = strKey + "E";
        synchronized (cipherMap) {
            if (cipherMap.containsKey(key)) {
                return cipherMap.get(key);
            }
            Security.addProvider(new SunJCE());
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, getKey(strKey));
            cipherMap.put(key, cipher);
            return cipher;
        }
    }

    private final static Cipher getDecryptCipher(String strKey) throws Exception {
        String key = strKey + "D";
        synchronized (cipherMap) {
            if (cipherMap.containsKey(key)) {
                return cipherMap.get(key);
            }
            Security.addProvider(new SunJCE());
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, getKey(strKey));
            cipherMap.put(key, cipher);
            return cipher;
        }
    }

    /**
     * 
     * 用户提交信息加密方式
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String encryptIn(String strIn) throws Exception {
        return encrypt(strIn, "11315china315");
    }

    /**
     * 
     * 用户提交信息解密方式
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String decryptIn(String strIn) throws Exception {
        return decrypt(strIn, "11315china315");
    }

    /**
     * 
     * 项目间信息加密方式
     * 
     * @Title encryptOut
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String encryptOut(String strIn) throws Exception {
        return encrypt(strIn, "11315china315事实上");
    }

    /**
     * 
     * 项目间信息解密方式
     * 
     * @Title decryptOut
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String decryptOut(String strIn) throws Exception {
        return decrypt(strIn, "11315china315事实上");
    }

    /**
     * 
     * 加密方法
     * 
     * @Title encrypt
     * @param strIn
     *            加密字符串
     * @param strKey
     *            加密密钥
     * @return
     * @throws Exception
     *             String
     */
    public static String encrypt(String strIn, String strKey) throws Exception {
        Cipher cipher = getEncryptCipher(strKey);
        byte[] strByte = cipher.doFinal(strIn.getBytes());
        return byte2hex(strByte);
    }

    /**
     * 
     * 解密方法
     * 
     * @Title decrypt
     * @param strIn
     *            解密字符串
     * @param strKey
     *            机密密钥
     * @return
     * @throws Exception
     *             String
     */
    public static String decrypt(String strIn, String strKey) throws Exception {
        Cipher cipher = getDecryptCipher(strKey);
        byte[] strByte = cipher.doFinal(hex2byte(strIn.getBytes()));
        return new String(strByte, "utf-8");
    }

    private final static Key getKey(String strKey) throws Exception {
        byte[] arrB = new byte[8];
        byte[] arrBTmp = strKey.getBytes();

        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }
        return new SecretKeySpec(arrB, "DES");
    }

    private final static byte[] hex2byte(byte[] b) {
        if ((b.length % 2) != 0)
            throw new IllegalArgumentException();
        byte[] b2 = new byte[b.length / 2];
        for (int n = 0; n < b.length; n += 2) {
            String item = new String(b, n, 2);
            int data = 0;
            try {
                data = Integer.parseInt(item, 16);
            } catch (Exception e) {
            }
            b2[n / 2] = (byte) data;
        }
        return b2;
    }

    private final static String byte2hex(byte[] b) {
        char[] c = new char[b.length * 2];
        for (int i = 0; i < b.length; i++) {
            byte b1 = b[i];
            c[(2 * i)] = DIGEST_ARRAY[((b1 & 0xF0) >> 4)];
            c[(2 * i + 1)] = DIGEST_ARRAY[(b1 & 0xF)];
        }
        return new String(c);
    }

    public static void main(String[] args) throws Exception {
//        long t0 = System.currentTimeMillis();
//        for (int i = 0; i < 1000; i++) {
//            final int num = i;
//            new Thread() {
//                public void run() {
//                    try {
//                        String s = SecurityService.encrypt("山东", "abcdefgh123" + num);
//                        s = SecurityService.decrypt(s, "abcdefgh123" + num);
//                    } catch (Exception e) {
//                        log.error("", e);
//                    }
//                }
//            }.start();
//        }
//        long t1 = System.currentTimeMillis();
//        System.out.println(t1 - t0);
//
        System.out.println(SecurityService.class.getSimpleName());
        System.out.println(SHA1("于国帅"));
    }
}
